<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
<!-- calculatorbuilder.qdoc -->
  <title>计算器创建示例 | Qt Designer 手册</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td ><a href="../qtdoc/index.html">Qt 5.14</a></td><td ><a href="qtdesigner-manual.html">Qt Designer Manual</a></td><td >Calculator Builder Example</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtdesigner-manual.html">Qt 5.14.2 参考文档</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar">
<div class="toc">
<h3><a name="toc">目录</a></h3>
<ul>
<li class="level1"><a href="#preparation">准备</a></li>
<li class="level1"><a href="#calculatorform-class-definition">定义 CalculatorForm 类</a></li>
<li class="level1"><a href="#calculatorform-class-implementation">实现 CalculatorForm 类</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">计算器创建示例</h1>
<span class="subtitle"></span>
<!-- $$$calculatorbuilder-brief -->
<p><i>Qt Designer</i> 窗体在运行时创建用户界面 。</p>
<!-- @@@calculatorbuilder -->
<!-- $$$calculatorbuilder-description -->
<div class="descr"> <a name="details"></a>
<p class="centerAlign"><img src="images/calculatorbuilder-example.png" alt="" /></p><p>我们使用 <a href="qtdesigner-calculatorform-example.html">Calculator Form</a> 示例中创建的窗体来显示在执行应用程序时可以生成相同的用户界面，或者在构建应用程序时可以定义相同的用户界面 。</p>
<a name="preparation"></a>
<h4 id="preparation">准备</h4>
<p><a href="qtdesigner-calculatorform-example.html">Calculator Form</a> 示例定义了一个无需修改即可使用的用户界面 。在本例中，我们使用一个 <a href="../qtcore/resources.html">资源文件</a> 来包含在前一个示例中创建的 <code>calculatorform.ui</code> 文件，但是它可以存储在磁盘上 。</p><p>为了在运行时生成窗体，我们的示例需要链接 <code>QtUiTools</code> 模块库。以下是我们使用的项目文件所包含的所有必要的信息:</p>
<pre class="cpp">

  HEADERS     = calculatorform.h
  RESOURCES   = calculatorbuilder.qrc
  SOURCES     = calculatorform.cpp \
                main.cpp
  QT += widgets uitools

</pre>
<p>所有其他必要的文件都像往常一样声明。</p>
<a name="calculatorform-class-definition"></a>
<h4 id="calculatorform-class-definition">定义 CalculatorForm 类</h4>
<p><code>CalculatorForm</code> 类定义了用于托管窗体用户界面的小部件:</p>
<pre class="cpp">

  <span class="keyword">class</span> CalculatorForm : <span class="keyword">public</span> <span class="type"><a href="../qtwidgets/qwidget.html">QWidget</a></span>
  {
      Q_OBJECT

  <span class="keyword">public</span>:
      <span class="keyword">explicit</span> CalculatorForm(<span class="type"><a href="../qtwidgets/qwidget.html">QWidget</a></span> <span class="operator">*</span>parent <span class="operator">=</span> nullptr);

  <span class="keyword">private</span> <span class="keyword">slots</span>:
      <span class="type">void</span> on_inputSpinBox1_valueChanged(<span class="type">int</span> value);
      <span class="type">void</span> on_inputSpinBox2_valueChanged(<span class="type">int</span> value);

  <span class="keyword">private</span>:
      <span class="type"><a href="../qtwidgets/qspinbox.html">QSpinBox</a></span> <span class="operator">*</span>ui_inputSpinBox1;
      <span class="type"><a href="../qtwidgets/qspinbox.html">QSpinBox</a></span> <span class="operator">*</span>ui_inputSpinBox2;
      <span class="type"><a href="../qtwidgets/qlabel.html">QLabel</a></span> <span class="operator">*</span>ui_outputWidget;
  };

</pre>
<p>注意，我们不需要包含头文件来描述用户界面。我们只使用 <code>uic</code> 所需的自动连接命名约定定义了两个公共槽，并声明了私有变量，在构造窗体提供的小部件后，我们将使用这些私有变量来访问它们 。</p>
<a name="calculatorform-class-implementation"></a>
<h4 id="calculatorform-class-implementation">实现 CalculatorForm 类</h4>
<p>我们将需要使用由 <code>libQtUiTools</code> 库提供的 <a href="../qtuitools/quiloader.html">QUiLoader</a> 类，因此我们首先确保包含模块头文件:</p>
<pre class="cpp">

  <span class="preprocessor">#include &lt;QtUiTools&gt;</span>

</pre>
<p>构造函数使用一个窗体加载器对象来构造我们通过 <a href="../qtcore/qfile.html">QFile</a> 对象从示例的资源中获取的用户界面:</p>
<pre class="cpp">

  CalculatorForm<span class="operator">::</span>CalculatorForm(<span class="type"><a href="../qtwidgets/qwidget.html">QWidget</a></span> <span class="operator">*</span>parent)
      : <span class="type"><a href="../qtwidgets/qwidget.html">QWidget</a></span>(parent)
  {
      <span class="type"><a href="../qtuitools/quiloader.html">QUiLoader</a></span> loader;

      <span class="type"><a href="../qtcore/qfile.html">QFile</a></span> file(<span class="string">&quot;:/forms/calculatorform.ui&quot;</span>);
      file<span class="operator">.</span>open(<span class="type"><a href="../qtcore/qfile.html">QFile</a></span><span class="operator">::</span>ReadOnly);
      <span class="type"><a href="../qtwidgets/qwidget.html">QWidget</a></span> <span class="operator">*</span>formWidget <span class="operator">=</span> loader<span class="operator">.</span>load(<span class="operator">&amp;</span>file<span class="operator">,</span> <span class="keyword">this</span>);
      file<span class="operator">.</span>close();

</pre>
<p>通过将用户界面包含在示例的资源中，我们确保在示例运行时它会出现。<code>loader.load()</code> 函数接受文件中包含的用户界面描述，并将窗体小部件构造为 <code>CalculatorForm</code> 的子小部件 。</p>
<p>我们对生成的用户界面中的三个小部件感兴趣:两个旋转框（spin box）和一个标签（label）。为了方便起见，我们从 <code>FormBuilder</code> 构造的小部件中检索到这些小部件的指针，并记录它们以供以后使用。 <code>qFindChild()</code> 模板函数允许我们查询小部件，以便找到已命名的子小部件 。</p>
<pre class="cpp">

      ui_inputSpinBox1 <span class="operator">=</span> findChild<span class="operator">&lt;</span><span class="type"><a href="../qtwidgets/qspinbox.html">QSpinBox</a></span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="string">&quot;inputSpinBox1&quot;</span>);
      ui_inputSpinBox2 <span class="operator">=</span> findChild<span class="operator">&lt;</span><span class="type"><a href="../qtwidgets/qspinbox.html">QSpinBox</a></span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="string">&quot;inputSpinBox2&quot;</span>);
      ui_outputWidget <span class="operator">=</span> findChild<span class="operator">&lt;</span><span class="type"><a href="../qtwidgets/qlabel.html">QLabel</a></span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="string">&quot;outputWidget&quot;</span>);

</pre>
<p>窗体加载器创建的小部件需要连接到 <code>CalculatorForm</code> 对象中的特殊命名的槽。我们使用Qt的元对象系统来实现这些连接:</p>
<pre class="cpp">

      <span class="type"><a href="../qtcore/qmetaobject.html">QMetaObject</a></span><span class="operator">::</span>connectSlotsByName(<span class="keyword">this</span>);

</pre>
<p>将窗体小部件添加到布局中，并设置窗口标题:</p>
<pre class="cpp">

      <span class="type"><a href="../qtwidgets/qvboxlayout.html">QVBoxLayout</a></span> <span class="operator">*</span>layout <span class="operator">=</span> <span class="keyword">new</span> <span class="type"><a href="../qtwidgets/qvboxlayout.html">QVBoxLayout</a></span>;
      layout<span class="operator">-</span><span class="operator">&gt;</span>addWidget(formWidget);
      setLayout(layout);

      setWindowTitle(tr(<span class="string">&quot;Calculator Builder&quot;</span>));
  }

</pre>
<p>除了我们从旋转框（spin box）中读取值并通过构造函数中记录的指针将结果写入输出小部件，窗体提供的两个修改小部件的槽的定义方式与 <a href="qtdesigner-calculatorform-example.html">Calculator Form</a> 示例中的类似:</p>
<pre class="cpp">

  <span class="type">void</span> CalculatorForm<span class="operator">::</span>on_inputSpinBox1_valueChanged(<span class="type">int</span> value)
  {
      ui_outputWidget<span class="operator">-</span><span class="operator">&gt;</span>setText(<span class="type"><a href="../qtcore/qstring.html">QString</a></span><span class="operator">::</span>number(value <span class="operator">+</span> ui_inputSpinBox2<span class="operator">-</span><span class="operator">&gt;</span>value()));
  }

  <span class="type">void</span> CalculatorForm<span class="operator">::</span>on_inputSpinBox2_valueChanged(<span class="type">int</span> value)
  {
      ui_outputWidget<span class="operator">-</span><span class="operator">&gt;</span>setText(<span class="type"><a href="../qtcore/qstring.html">QString</a></span><span class="operator">::</span>number(value <span class="operator">+</span> ui_inputSpinBox1<span class="operator">-</span><span class="operator">&gt;</span>value()));
  }

</pre>
<p>这种方法的优点是，我们可以在应用程序运行时替换窗体，但仍然可以操作其中包含的小部件，只要为它们指定了适当的名称 。</p>
<p><a href="https://code.qt.io/cgit/qt/qttools.git/tree/examples/designer/calculatorbuilder?h=5.14">项目示例 @ code.qt.io</a></p>
</div>
<!-- @@@calculatorbuilder -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2020 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>
